package com.ld.zxw.util;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.FSDirectory;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.ld.zxw.Documents.Documents;
import com.ld.zxw.config.LuceneDataSource;
import com.ld.zxw.config.LucenePlusConfig;

public class CommonUtil {

	private static Logger log = Logger.getLogger(CommonUtil.class);

	/**
	 * 关闭 indexWriter
	 * @param indexWriter
	 */
	public static void colseIndexWriter(IndexWriter indexWriter){
		if(indexWriter != null) {
			try {
				indexWriter.close();
			} catch (IOException e) {
				log.error("colseIndexWriter", e);
			}
		}
	}
	
	/**
	 * 关闭 FSDirectory
	 * @param fsd
	 */
	public static void colseDirectory(FSDirectory fsd) {
		if(fsd != null) {
			try {
				fsd.close();
			} catch (Exception e) {
				log.error("colseDirectory", e);
			}
		}
	}
	/**
	 * 关闭 DirectoryReader
	 * @param dir
	 */
	public static void colseDirectoryReader(DirectoryReader dir) {
		if(dir != null) {
			try {
				dir.close();
			} catch (IOException e) {
				log.error("colseDirectoryReader", e);
			}
		}
	}

	/**
	 * Object 转 Document
	 * @param <T>
	 * @param objs
	 * @param LucenePlusConfig
	 * @return
	 */
	public synchronized static <T> List<Document> turnDoc(List<T> objs,LucenePlusConfig lucenePlusConfig){
		List<Document> documents = Lists.newArrayList();
		Map<String, Float> boostField = lucenePlusConfig.getBoostField();
		int size = objs.size();
		for (int i = 0; i < size; i++) {
			documents.add(objDoc(objs.get(i), boostField,lucenePlusConfig.getParticipleField()));
		}
		return documents;

	}
	public synchronized static <T> Document turnDoc(T obj,LucenePlusConfig lucenePlusConfig){
		Map<String, Float> boostField = lucenePlusConfig.getBoostField();
		return objDoc(obj, boostField, lucenePlusConfig.getParticipleField());
	}

	/**
	 * Object 转 Document  通用
	 * @param obj
	 * @param boost
	 * @return
	 */
	public synchronized static Document objDoc(Object obj,Map<String, Float> boost,List<String> queryfields) {
		Documents doc = new Documents();
		Field[] fields = obj.getClass().getDeclaredFields();
		List<BoostDto> list = getBoosts();
		if(list == null || list.size() < 1) {
			for(int i=0;i < fields.length; i++) {
				Field field = fields[i];
				field.setAccessible(true);
				String name = field.getName();
				String type = field.getType().getName();
				Object val = new Object();
				try {
					val = field.get(obj);
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
				if(boost != null) {
					doc.put(name, val, getType(name, type, queryfields), boost.get(name));
				}else {
					doc.put(name, val, getType(name, type, queryfields), 1);
				}
			}
		}else {
			for(int i=0;i < fields.length; i++) {
				Field field = fields[i];
				field.setAccessible(true);
				String name = field.getName();
				String type = field.getType().getName();
				Object val = new Object();
				try {
					val = field.get(obj);
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
				doc.put(name, val, type, boost.get(name)+getBoost(name,list));

			}
		}
		return doc.getDocument();
	}

	/**
	 * 数据类型处理
	 * @param name
	 * @param type
	 * @param fields
	 * @return
	 */
	public synchronized static String getType(String name,String type,List<String> fields) {
		String typeName = null;
		//类型修正和转换
		String[] split = type.split("\\.");
		if(split.length > 1) {
			typeName = split[split.length-1];
		}else {
			typeName = type;
		}
		//分词字段
		if(fields != null) {
			if(fields.contains(name)) {
				typeName = "text";
			}
		}
		return typeName.toLowerCase();
	}

	/**
	 * 获取排名分词
	 * @param name
	 * @param boosts 
	 * @return
	 */
	public synchronized static float getBoost(String name, List<BoostDto> boosts) {
		int size = boosts.size();
		float k =0;
		for (int i = 0; i < size; i++) {
			BoostDto boostDto = boosts.get(i);
			if(boostDto.equals(name)) {
				k = boostDto.getBoost();
				boosts.remove(i);
				break;
			}
		}
		return k;
	}


	/**
	 * 过滤非法字符
	 * @param str 元数据
	 * @param filter 非法数据
	 * @return
	 */
	public synchronized static String IllegalFiltering(String str,String filter){
		if(filter != null){
			return str;
		}else{
			char[] data = getChar(str);
			char[] fiter = getChar(filter);
			String key="";
			for (int i = 0; i < data.length; i++) {
				if(isFlag(fiter, data[i])){
					key+=String.valueOf(data[i]);
				}
			}
			return key;
		}
	}
	
	private static char[] getChar(String str){
		char[] c=new char[str.length()];
		c=str.toCharArray();
		return c;
	}
	public static boolean isFlag(char[] fiter,char vue){
		boolean flag = true;
		for (int j = 0; j < fiter.length; j++) {
			if(fiter[j] == vue){
				flag=false;
				break;
			}
		}
		return flag;
	}

	/**
	 * 获取动态权重
	 * @return
	 */
	public static List<BoostDto> getBoosts(){
		if(LuceneDataSource.build().jedis == null) {
			return null;
		}else {
			List<String> lrange = LuceneDataSource.build().jedis.lrange("LuceneBoost_LD", 0, Integer.MAX_VALUE);
			return orObj(lrange);
		}
	}

	public static List<BoostDto> orObj(List<String> list){
		List<BoostDto> dtos = Lists.newArrayList();
		int size = list.size();
		for (int i = 0; i < size; i++) {
			dtos.add(JSONObject.parseObject(list.get(i), BoostDto.class));
		}
		return dtos;

	}
	
	/**
	 * 同步查询 reader
	 * @param LucenePlusConfig
	 * @param writer
	 */
	public static synchronized void refresh(LucenePlusConfig lucenePlusConfig,IndexWriter writer) {
		IndexReader reader = null;
		try {
			reader = DirectoryReader.open(writer);
		} catch (IOException e) {
			log.error("refresh-error", e);
		}
		lucenePlusConfig.setIndexSearcher(new IndexSearcher(reader));
		if(!lucenePlusConfig.getDevMode()){
			try {
				writer.commit();
			} catch (Exception e) {
				try {
					writer.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				log.error("writer.commit-error", e);
			}
		}
	}
}
